<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>评审专家打分</title>
@include('common-css')
<style>
header {
}

h1 {
    text-align: center;
    color: #10479e;
    font-weight: bold;
    font-size: 24px;
    cursor: default;
    font-family: serif;
}

.page-body {
    padding: 10px;
}

.attr-table {
    width: 100%;
}

.attr-table td {
    padding: 10px 10px;
    vertical-align: top;
}

.attr-table tr td:first-child {
    font-size: 14px;
}

h3 {
    font-weight: bold;
}

.score-table {
}

.ant-table-tbody > tr > td, .ant-table-thead > tr > th {
    vertical-align: middle;
    line-height: 25px;
    font-size: 12px;
}

.remark-example {
    font-size: 12px;
    line-height: 20px;
    color: #666;
}

.remark-example label {
    font-weight: bold;
}

.remark-example p {
}

.required {
    color: red;
}
</style>
</head>
<body>
<div id="app">
</div>
</body>
</html>

<script id="appTemplate" type="x-template">
<div>

    <header class="special">
        <h1>评审专家打分</h1>
        <span style="flex: 1;"></span>
        <div style="margin-top: 10px; margin-bottom: 10px">
            <label style="color: green">评审总得分：@{{ score }}</label>
            <a-button style="margin-left: 20px" v-if="!is_submitted" type="primary"
                      @click="handleSaveScore">保存修改
            </a-button>
        </div>
    </header>

    <div class="page-body">
        <p class="hint-text" style="margin-bottom: 20px;">填写说明: <span class="required">*</span> 标注的项为必填项，必须全部填写才能提交评分</p>
        <table class="attr-table">
            <tr>
                <td width="250">项目名称</td>
                <td style="color: blue;">{{ $project->project_name }}</td>
            </tr>
            <tr>
                <td>附件证明材料是否真实有效 <span class="required">*</span></td>
                <td>
                    <a-radio-group :disabled='is_submitted' size="small" v-model="is_evidence_material_valid"
                                   @change="isDataDirty = true">
                        <a-radio :value="1">是</a-radio>
                        <a-radio :value="0">否</a-radio>
                    </a-radio-group>
                    <a style="font-size: 14px;" href="/home/view-attachments?project_id={{ $project->id }}" target="_blank">查看附件</a>
                </td>
            </tr>
            <tr>
                <td>
                    专家意见 <span class="required">*</span>
                </td>
                <td>
                    <div style="display: flex;">
                        <a-textarea style="flex: 1;" :disabled='is_submitted' :autosize="{minRows: 5, maxRows: 8}" :maxlength="reviewerRemarkMaxLen"
                                    v-model="remark"
                                    placeholder="请填写对该项目的总体意见"
                                    @change="isDataDirty = true"></a-textarea>
                        <div class="remark-example" style="flex: 1; padding: 0 10px;">
                            <label>填写示例</label>
                            <p>&nbsp;&nbsp;&nbsp;&nbsp;（从研究成果的主要性能参数，技术经济指标和总体技术水平以及与国内外同类项目技术水平的比较情况，社会经济效益、推广应用前景等方面填写意见）</p>
                            <p>&nbsp;&nbsp;&nbsp;&nbsp;经过审查，该研究成果关键技术整体上达到（国际先进及以上水平/国内领先/国内先进），成果转化（程度高/程度较高/有一定程度），对推动交通建设科技进步有（重大作用/很大作用/较大作用），并取得了（重大/显著/一定）的社会经济效益，可推荐为{{ $awardIssue }}科学技术进步奖。</p>
                        </div>
                    </div>
                </td>
            </tr>
            <tr>
                <td>评分表（共 4 个指标）</td>
                <td>
                    <a-table class="score-table"
                             size="small"
                             rowKey="key"
                             :columns="scoreTableColumns"
                             :dataSource="scoreData"
                             :loading="loadingPageData"
                             :pagination="false">
                        <span slot="realScoreTitle">
                            实得分  <span class="required">*</span>
                        </span>
                        <span slot="evaluation_index" slot-scope="text, record">
                            <h3 style="display: inline;">@{{ record.evaluation_index }}</h3>
                            <p>@{{ record.evaluation_index_meaning }}</p>
                            <p><a style="font-size: 12px;" :href="`/home/view-form?id={{ $project->id }}${record.application_form_anchor}`" target="_blank">查看申报书相关章节</a></p>
                        </span>
                        <p slot="method_of_marking" slot-scope="text, record" v-html="record.method_of_marking"></p>
                        <span slot="real_score" slot-scope="text, record">
                    <a-input-number :disabled='is_submitted' :min="0" :max="Number(record.standard_score)"
                                    :precision="0" v-model="record.real_score"
                                    @change="isDataDirty = true"></a-input-number>
                </span>
                        <span slot="remarks" slot-scope="text, record">
                    <a-textarea :disabled='is_submitted' :autosize="{minRows: 3, maxRows: 8}"
                                :maxlength="evaluationIndexScoreRemarkMaxLen"
                                v-model="record.remarks"
                                @change="isDataDirty = true"></a-textarea>
                </span>
                    </a-table>
                </td>
            </tr>
        </table>

    </div>

</div>
</script>

@include('common-js')

<script>
var queryParams = parseUrl(location.href).params;

const scoreTableColumns = [
    {
        width: 300,
        title: '评价指标',
        dataIndex: 'evaluation_index',
        scopedSlots: {
            customRender: 'evaluation_index'
        }
    },
    {
        width: 220,
        title: '评分方法及标准',
        dataIndex: 'method_of_marking',
        scopedSlots: {
            customRender: 'method_of_marking'
        }
    },
    {
        width: 80,
        title: '标准分',
        dataIndex: 'standard_score',
        scopedSlots: {
            customRender: 'standard_score'
        }
    },
    {
        width: 100,
        slots: {
            title: 'realScoreTitle'
        },
        dataIndex: 'real_score',
        scopedSlots: {
            customRender: 'real_score'
        }
    },
    {
        width: 200,
        title: '专家意见',
        dataIndex: 'remarks',
        scopedSlots: {
            customRender: 'remarks'
        }
    }];
</script>

<script>
var app = new Vue({
    el: '#app',
    template: '#appTemplate',
    data: {
        loadingPageData: false,

        scoreTableColumns,
        reviewerRemarkMaxLen: 1000,
        evaluationIndexScoreRemarkMaxLen: 1000,

        isDataDirty: false,
        is_submitted: false,
        is_evidence_material_valid: null,
        remark: '',
        scoreData: [
            {
                key: '1',
                evaluation_index: '技术创新程度',
                application_form_anchor: '#c3_zykjcx',
                evaluation_index_meaning: '指项目在技术开发中解决关键技术难题并取得技术突破，掌握核心技术并进行集成创新的程度，自主创新技术在总体技术中的比重。（重点参考评价报告、查新报告、专利、论文、软著等材料中的创新点）',
                method_of_marking: '有重大突破或实质性创新 25-30; <br>有较大突破或创新 18-24; <br>有一定创新	11-17; <br>创新一般 ≤10',
                standard_score: '30',
                real_score: '',
                remarks: ''
            },
            {
                key: '2',
                evaluation_index: '技术先进程度',
                application_form_anchor: '#c3_kgpj',
                evaluation_index_meaning: '指与国内外最先进技术相比，总体技术水平、主要技术（性能、性状、工艺参数等）、经济（投入产出比、性能价格比、成本、规模等）、环境、生态等指标所处的位置。（重点参考评价报告中的技术先进性水平）',
                method_of_marking: '达到国际领先水平 17-20; <br>达到国际先进水平 13-16; <br>达到国内领先水平 9-12; <br>达到国内先进水平 ≤8',
                standard_score: '20',
                real_score: '',
                remarks: ''
            },
            {
                key: '3',
                evaluation_index: '技术应用推广情况',
                application_form_anchor: '#c4_s1_tgyyqk',
                evaluation_index_meaning: '指自主研发的关键技术在行业竞争中发挥作用的情况，如：适应市场需求，形成竞争实力，替代进口或突破技术壁垒进入国际市场等。已经取得自主知识产权或形成行业工法、技术标准的项目可酌情加分。（重点参考评价报告中推广应用前景评语、应用证明材料、成功案例、已获得标准、工法以及产业化情况）',
                method_of_marking: '市场需求度高，具有国际市场竞争优势 17-20; <br>市场需求度较高，具有国内市场竞争优势 13-16; <br>有一定市场需求与市场竞争能力 9-12; <br>市场需求、市场竞争能力一般 ≤8',
                standard_score: '20',
                real_score: '',
                remarks: ''
            },
            {
                key: '4',
                evaluation_index: '经济效益',
                application_form_anchor: '#c4_s2_jlnjjxy',
                evaluation_index_meaning: '指成果在应用后的直接或间接经济效益（包括主要完成单位已经通过技术转让、增收节支、提高效益、降低成本获得的新增利润、税收及他人由于使用该技术而产生的经济收益）（重点参考经济效益证明/分析报告）',
                method_of_marking: '取得重大/显著的经济效益 17-20; <br>取得较大的经济效益 13-16; <br>取得一定的经济效益 9-12; <br>经济效益一般 ≤8',
                standard_score: '20',
                real_score: '',
                remarks: ''
            },
            {
                key: '5',
                evaluation_index: '社会效益-数字智慧',
                application_form_anchor: '#c4_s2_shxy',
                evaluation_index_meaning: '指工程建设和成果技术创新在数字智慧等高新技术领域实现技术跨越，推动公路智能建造和智慧工地建设，促进公路交通数字化转型等方面发挥重要作用（主要包括设计建造、管理、养护、运营等）。',
                method_of_marking: '数智化水平很高，对推动行业高新技术进步作用显著 5; <br>数智化水平较高，对推动行业高新技术进步作用明显 4; <br>数智化水平一般，对推动行业高新技术进步作用不明显 ≤3',
                standard_score: '5',
                real_score: '',
                remarks: ''
            },
            {
                key: '6',
                evaluation_index: '社会效益-绿色低碳',
                application_form_anchor: '#c4_s2_shxy',
                evaluation_index_meaning: '指在提升行业结构优化升级、产品更新换代，促进经济社会节能环保和绿色发展，实现“双碳”目标等方面所起的示范和引领作用。推广后对生态环境造成负面影响的，不予评审。（主要包括节能环保、绿色低碳、安全可靠等）。',
                method_of_marking: '与同类技术比较节能环保效果显著，推广后能有效促进绿色发展和加快实现“双碳”目标 5; <br>与同类技术比较节能环保效果良好，推广后有利于绿色发展和加快实现“双碳”目标 4; <br>与同类技术比较节能环保效果一般，推广后对实现绿色发展和加快实现“双碳”目标有一定作用 ≤3',
                standard_score: '5',
                real_score: '',
                remarks: ''
            },
        ]
    },
    computed: {
        score() {  // 总分
            return this.scoreData.reduce((result, item) => result + (item.real_score === undefined ? 0 : Number(item.real_score)), 0)
        },
        isScoreFinished() {  // 是否所有的评分项都已填写
            if (this.isEmpty(this.is_evidence_material_valid)) {
                return false;
            }
            if (this.isEmpty(this.remark)) {
                return false;
            }
            for (let item of this.scoreData) {
                if (this.isEmpty(item.real_score)) {
                    return false
                }
            }
            return true
        }
    },
    mounted() {
        this.reloadPageData()
    },
    methods: {
        handleSaveScore() {
            let verifyResult = this.verifyScoreData(false);
            if (!verifyResult.ok) {
                let msg = '';
                for ([key, errorMsg] of verifyResult.bad_keys) {
                    msg += errorMsg + "\n"
                }
                alert(msg);
                return
            }

            let scores = [];
            for (let scoreDataItem of this.scoreData) {
                let scoresItem = subset(scoreDataItem, ['key', 'evaluation_index', 'standard_score', 'real_score', 'remarks']);
                if (scoresItem.real_score === undefined) {
                    scoresItem.real_score = null
                }
                scores.push(scoresItem)
            }
            axios.post('/api/review/save-project-score', {
                project_id: queryParams.project_id,
                score: this.isScoreFinished ? this.score : null,
                is_evidence_material_valid: this.is_evidence_material_valid,
                remark: this.remark,
                form_data: {scores}
            }).then(response => {
                if (response.data.ok) {
                    success('保存成功');
                    this.isDataDirty = false
                } else {
                    error('保存失败：' + response.data.mgs)
                }
            })
        },
        verifyScoreData(checkCanEmpty = false) {
            let bad_keys = new Map();
            let keys = ['score', 'is_evidence_material_valid', 'remark'];
            let keyDisplayNames = ['总分', '附件证明材料是否真实有效', '专家意见'];
            for (let i = 0; i < keys.length; i++) {
                let key = keys[i];
                let value = this[key];
                if (typeof (value) === 'string') {
                    value = value.trim()
                }
                let keyDisplayName = keyDisplayNames[i];
                if (this.isEmpty(value)) {
                    if (checkCanEmpty) {
                        bad_keys.set(key, `${keyDisplayName} 不能为空`)
                    }
                    continue
                }

                if (key === 'score') {
                    value = Number(value);
                    if (value < 0 || value > 100) {
                        bad_keys.set(key, `${keyDisplayName} 只能位于 [0, 100] 之间`)
                    }
                }
                if (key === 'remark' && value.length > this.reviewerRemarkMaxLen) {
                    bad_keys.set(key, `${keyDisplayName} 最多 ${this.reviewerRemarkMaxLen} 字符`)
                }
            }

            let scoreData = this.scoreData;
            for (let i = 0; i < scoreData.length; i++) {
                let item = scoreData[i];
                const evaluation_index = item.evaluation_index;
                let key = `评价指标-${evaluation_index}`;

                const standard_score = Number(item.standard_score);
                let real_score = item.real_score;
                if (this.isEmpty(real_score)) {
                    if (checkCanEmpty) {
                        bad_keys.set(key, evaluation_index + " 不能为空")
                    }
                } else {
                    real_score = Number(real_score);
                    if (real_score < 0 || real_score > standard_score) {
                        bad_keys.set(key, `${key} 的实得分只能位于 [0, ${standard_score}] 之间`)
                    }
                }

                let remarks = item.remarks;
                if (typeof remarks === 'string' && remarks.length > this.evaluationIndexScoreRemarkMaxLen) {
                    bad_keys.set(key, `${key} 的备注最多 ${this.evaluationIndexScoreRemarkMaxLen} 字符`)
                }
            }

            return {
                'ok': bad_keys.size === 0,
                bad_keys
            }
        },
        isEmpty(value) {
            return value === undefined || value === null || value === '' || (value instanceof Array && value.length === 0)
        },
        reloadPageData() {
            this.loadingPageData = true;
            axios.get('/api/review/get-project-score', {
                'params': {
                    project_id: queryParams.project_id
                }
            }).then(response => {
                if (response.data.ok) {
                    this.isDataDirty = false;
                    let reviewer_score_project = response.data.reviewer_score_project;
                    this.is_submitted = Boolean(reviewer_score_project.is_submitted);
                    this.is_evidence_material_valid = reviewer_score_project.is_evidence_material_valid;
                    this.remark = reviewer_score_project.remark;
                    const form_data = reviewer_score_project.form_data;
                    const scores = form_data.hasOwnProperty('scores') ? form_data.scores : [];
                    for (let scoreDataItem of this.scoreData) {
                        for (let scoresItem of scores) {
                            if (scoreDataItem.key === scoresItem.key) {
                                this.$set(scoreDataItem, 'real_score', scoresItem.real_score);
                                this.$set(scoreDataItem, 'remarks', scoresItem.remarks);
                                break
                            }
                        }
                    }
                } else {
                    error('加载页面数据失败：' + response.data.msg)
                }
                this.loadingPageData = false
            })
        },
    }
})
</script>
